(function ($) {
    var currentPageIndex,       // global reference for the current page index
        currentBookIndex,       // global reference for the current book index
        excerptHeight,          // used as multiplier for page animations
        excerptContent,         // global reference for 'div.excerpt-content'
        Controls = {},          // excerpt navigation object
        Excerpt,                // global reference for the Excerpt Object itself
        Books = [],             // a collection of Excerpt's book children
        options,                // excerpt options
        uiTheme;                // hold ui theme classes

    function init() {
        var _bookTitles = [];     // temporary storage for book titles

        uiTheme = {
            'default'   : 'xl-widget-excerpt-theme-default',
            'metro'     : 'xl-widget-excerpt-theme-metro'
        };

        currentPageIndex    = 0;
        currentBookIndex    = getUrlParams('bookIndex') || 0;
        excerptContent      = $('.excerpt-content', Excerpt);

        // apply a theme to the excerpt
        Excerpt.addClass(uiTheme[options.theme]);

        // get book collection and populate the Books object
        // with corresponding title and page number
        $('ul', excerptContent).each(function (ix, elem) {
            var _title = $(elem).attr('title'),
                _pages = $('img', elem).map(function () {
                    return $(this).attr('data-page') || parsePageNumber($(this).attr('src'));
                });

            Books.push({
                title : _title,
                pages : $.makeArray(_pages)
            });

            _bookTitles.push(_title);
        });

        // populate pageList
        for (var i = 0, l = Books.length; i < l; i += 1) {
            Books[i].pageList = '<span class="excerpt-selection">' + Books[i].pages[0] + '</span><ul><li class="opt">';
            Books[i].pageList += Books[i].pages.join('</li><li class="opt">') + '</li></ul>';
        }

        // populate bookList
        // a list with only one item is nonsense,
        // so let's check that out
        if (_bookTitles.length > 1) {
            Books.bookList = '<span class="excerpt-selection">' + _bookTitles[0] + '</span><ul><li class="opt">';
            Books.bookList += _bookTitles.join('</li><li class="opt">') + '</li></ul>';
        }
    }

    /**
     * gets the parameters passed on the URL
     * @param  {string} name the parameter key
     * @return {multi} returns an object if name is not defined
     *                 returns the value of the parameter key if name is defined
     *                 returns undefined if URL contains no parameter
     */
    function getUrlParams(name) {
        var url = window.location.href,
            paramString = url.match(/\?(.*)$/),
            paramObject;

        if (paramString !== null && paramString.length > 1) {
            paramObject = (function (){
                var params = paramString[1].split('&'),
                    obj = {},
                    temp;

                for (var i = 0, l = params.length; i < l; i++) {
                    temp = params[i].split('=');
                    obj[temp[0]] = decodeURIComponent(temp[1]);
                }

                return obj;
            }());

            return name ? paramObject[name] : paramObject;
        } else {
            return undefined;
        }
    }

    function stepNumToBound(num, lb, ub, step) {
        num += step;

        return (num < lb) ? lb : (num > ub) ? ub : num;
    }

    /**
     * creates the initial navigational control for the excerpt
     * pages and book titles are base on Books Collection
     * @return {void} no return value
     */
    function generateControls() {
        var navTypeClass = (options.theme === 'metro') ? 'xl-nav-vertical' : 'xl-nav-horizontal';

        Controls.container  = $('<ul class="xl-nav ' + navTypeClass + ' excerpt-controls" />');
        Controls.buttonPrev = $('<li class="excerpt-button excerpt-button-prev" />');
        Controls.buttonNext = $('<li class="excerpt-button excerpt-button-next">');
        Controls.pageSelect = $('<li class="submenu-parent excerpt-dropdown excerpt-pageselect" />').html(Books[0].pageList);

        Controls.container.append(Controls.pageSelect);

        // create bookSelect control only if bookList is a qualified list
        if (Books.bookList) {
            Controls.bookSelect = $('<li class="submenu-parent excerpt-dropdown excerpt-bookselect" />').html(Books.bookList);
            Controls.container.append(Controls.bookSelect);
        }

        if (options.theme === 'metro') {
            Controls.container.append(Controls.buttonPrev);
            Controls.container.append(Controls.buttonNext);
        } else if (options.theme === 'default') {
            Controls.container.prepend(Controls.buttonNext);
            Controls.container.prepend(Controls.buttonPrev);
        }

        // inject the control to the document
        excerptContent.before(Controls.container);
    }

    /**
     * extracts the filename of the image and converts underscores to spaces
     * @param  {string} stringToParse URL of the image
     * @return {string}               the page number
     */
    function parsePageNumber(stringToParse) {
        var regex = /\/([\w\d]+)\.(gif|jpg|png)$/;

        return stringToParse.match(regex)[1].replace('_', ' ');
    }

    /**
     * updates the excerpt's contents based on the supplied bookIndex
     * @param  {int} bookIndex the book index
     * @return {void}          no return value
     */
    function updateToBook(bookIndex) {
        var books = $('ul', excerptContent),
            currentBook = $(books[bookIndex]);

        books.hide();
        currentBook.fadeIn('slow');

        // there are cases when a book has different layouts
        // e.g. square, portrait, landscape
        // so we need to update the multiplier
        excerptHeight = $('li', currentBook).innerHeight();

        // ensure books are set back to margin: 0;
        books.css({margin: 0});

        // update page selections
        Controls.pageSelect.html(Books[bookIndex].pageList);

        // update initial book selection
        if (Controls.bookSelect) {
            $('.excerpt-selection', Controls.bookSelect).text(Books[bookIndex].title);
        }

        // set currentPageIndex back to 0
        currentPageIndex = 0;

        adjustLayout();
    }

    /**
     * sets the height of the excerpt container to ensure the full page is shown
     * @return {void} no return value
     */
    function adjustLayout() {
        if (Math.floor(parseFloat(excerptContent.innerHeight())) !== excerptHeight) {
            excerptContent.animate({
                height : excerptHeight + 'px'
            }, 1000);
        }
    }

    /**
     * binds events to excerpt controls
     * @return {void} no return value
     */
    function attachEvents() {
        var dropdowns = $('.excerpt-dropdown', Excerpt);

        dropdowns.click(function (event) {
            var target      = $(event.target),
                subNav      = $('ul', this),
                currTarget  = event.currentTarget;

            if (currTarget === this) {
                subNav.show();
            }

            if (target.is('li.opt')) {
                $('.excerpt-selection', this).text(target.text());

                if ($(currTarget).hasClass('excerpt-pageselect')) {
                    gotoPage($(event.target).index());
                } else if ($(currTarget).hasClass('excerpt-bookselect')) {
                    gotoBook($(event.target).index());
                }

                subNav.hide();
            }
        });

        dropdowns.mouseleave(function () {
            $('ul:visible', this).hide();
        });

        Controls.buttonNext.click(gotoNextPage);
        Controls.buttonPrev.click(gotoPrevPage);
    }


    // ===========================================================
    // Event Handlers
    // ===========================================================

    function gotoPage(pageIndex) {
        pageIndex = stepNumToBound(pageIndex, 0, Books[currentBookIndex].pages.length - 1, 0);

        if (pageIndex !== currentPageIndex) {
            var books       = $('ul', excerptContent),
                currentBook = $(books[currentBookIndex]);

            // animate the page when updating
            currentBook.animate({
                'margin-top' : -(excerptHeight * pageIndex) + 'px'
            }, 500, function () {
                // update dropdown text to the current page
                $('.excerpt-selection', Controls.pageSelect).text(Books[currentBookIndex].pages[pageIndex]);
            });

            // update currentPageIndex
            currentPageIndex = pageIndex;
        }
    }

    function gotoPrevPage() {
        gotoPage(currentPageIndex - 1);
    }

    function gotoNextPage() {
        gotoPage(currentPageIndex + 1);
    }

    function gotoBook(bookIndex) {
        if (bookIndex !== currentBookIndex) {
            updateToBook(bookIndex);
            currentBookIndex = bookIndex;
        }
    }


    // ===========================================================
    // The main function
    // ===========================================================

    $.fn.excerpt = function (opt) {
        Excerpt = $(this);

        options = $.extend({
            theme : 'default'
        }, opt);

        $('img', Excerpt).imagesLoaded(function () {
            init();
            generateControls();
            updateToBook(currentBookIndex);
            attachEvents();
        });


        // expose some internal functions
        $.fn.extend({
            excerpt_gotoBook    : gotoBook,
            excerpt_gotoPage    : gotoPage,
            excerpt_next        : gotoNextPage,
            excerpt_prev        : gotoPrevPage
        });
    };

    // run the plugin
    $(document).ready(function () {
        $('.xl-widget-excerpt').addClass('js').excerpt();
    });
}(jQuery));

// imagesloaded plugin
(function(c,n){var k="";c.fn.imagesLoaded=function(l){function m(){var b=c(h),a=c(g);d&&(g.length?d.reject(e,b,a):d.resolve(e));c.isFunction(l)&&l.call(f,e,b,a)}function i(b,a){b.src===k||-1!==c.inArray(b,j)||(j.push(b),a?g.push(b):h.push(b),c.data(b,"imagesLoaded",{isBroken:a,src:b.src}),o&&d.notifyWith(c(b),[a,e,c(h),c(g)]),e.length===j.length&&(setTimeout(m),e.unbind(".imagesLoaded")))}var f=this,d=c.isFunction(c.Deferred)?c.Deferred():
0,o=c.isFunction(d.notify),e=f.find("img").add(f.filter("img")),j=[],h=[],g=[];e.length?e.bind("load.imagesLoaded error.imagesLoaded",function(b){i(b.target,"error"===b.type)}).each(function(b,a){var e=a.src,d=c.data(a,"imagesLoaded");if(d&&d.src===e)i(a,d.isBroken);else if(a.complete&&a.naturalWidth!==n)i(a,0===a.naturalWidth||0===a.naturalHeight);else if(a.readyState||a.complete)a.src=k,a.src=e}):m();return d?d.promise(f):f}})(jQuery);

